/*
 * File:    SocketStatistics.java
 * Created: 24-Dec-2006
 * Version: $Id$
 *
 * COPYRIGHT (C) 2006, Bitgate Software, LLC.  All Rights Reserved.
 *
 * software@bitgatesoftware.com
 */

package com.bitgate.util.socket;

import static com.bitgate.util.debug.Debug.*;

import java.util.ArrayList;

import com.bitgate.util.statistics.Statistics;
import com.bitgate.util.statistics.StatisticsInterface;

/**
 * This class contains a mechanism to output the statistics of the number of reads, writes, and the amount of traffic that was
 * sent to and from the server that uses the socket classes herein.  If any classes are used outside of this server, there will
 * be no accurate way to determine the bandwidth used by this system.  This mechanism uses <code>bitgate.util.statistics</code>
 * to gather statistics, and provides a mechanism to output those stats in a way that can be dumped to a file, or displayed
 * on the console.  The frequency of said statistics is dependant on the frequency of output of the statistics engine.
 * <p/>
 * This code has not been tested on a high load, and therefore, may not be thread-safe.  I may add some functionality to
 * make this threadsafe if required.
 * <p/>
 * TODO: Use AtomicLong and AtomicInt classes to handle the threadsafe issues.
 *
 * @author Kenji Hollis &lt;kenji@bitgatesoftware.com&gt;
 * @version $Id$
 */
public class SocketStatistics implements StatisticsInterface
{
    private static final SocketStatistics _default = new SocketStatistics();
    private int numReads, numWrites;
    private long bytesRead, bytesWrite;

    private SocketStatistics()
    {
		this.numReads = 0;
		this.numWrites = 0;
		this.bytesRead = 0;
		this.bytesWrite = 0;
	
		Statistics.getDefault().register(this);
    }

    /**
     * Returns the default instance of the class.
     *
     * @return <code>static SocketStatistics</code> default instance of the class.
     */
    public static SocketStatistics getDefault()
    {
    	return _default;
    }

    public ArrayList<String> getStatistics()
    {
		if (this.numReads == 0 && this.numWrites == 0) {
		    return null;
		}

		String statOut = "Read\tWrite\tBRead\tBWrite\n" + this.numReads + "\t" + this.numWrites + "\t" + this.bytesRead + "\t" +
			this.bytesWrite + "\n";
		ArrayList<String> listOut = new ArrayList<String>();
	
		listOut.add(statOut);
		resetStatistics();
	
		return listOut;
    }

    /**
     * Increases the number of bytes read.
     *
     * @param bytes The number of bytes read.
     */
    public void increaseReads(long bytes)
    {
    	if (bytes != -1) {
			this.numReads++;
			this.bytesRead += bytes;
	
			if (isDebugEnabled()) {
				debug("Increase reads: total reads='" + this.numReads + "' bytes='" + bytes + "' total='" + this.bytesRead + "'");
			}
    	}
	}

    /**
     * Increases the number of bytes written.
     *
     * @param bytes The number of bytes written.
     */
    public void increaseWrites(long bytes)
    {
    	if (bytes != -1) {
			this.numWrites++;
			this.bytesWrite += bytes;
		
			if (isDebugEnabled()) {
				debug("Increase writes: total writes='" + this.numWrites + "' bytes='" + bytes + "' total='" + this.bytesWrite + "'");
			}
    	}
    }

    public void resetStatistics()
    {
		this.numReads = 0;
		this.numWrites = 0;
		this.bytesRead = 0;
		this.bytesWrite = 0;
    }
}
